home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / EXEC.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  34KB  |  1,513 lines

  1. /*    This file is for functions dealing with execution of
  2.     commands, command lines, buffers, files and startup files
  3.  
  4.     written 1993 by Daniel Lawrence                */
  5.  
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "eproto.h"
  9. #include    "edef.h"
  10. #include    "elang.h"
  11.  
  12. /* namedcmd:    execute a named command even if it is not bound */
  13.  
  14. PASCAL NEAR namedcmd(f, n)
  15.  
  16. int f, n;    /* command arguments [passed through to command executed] */
  17.  
  18. {
  19.     int (PASCAL NEAR *kfunc)();     /* ptr to the function to execute */
  20.     char buffer[NSTRING];        /* buffer to store function name */
  21.     int status;
  22.  
  23.     /* if we are non-interactive.... force the command interactivly */
  24.     if (clexec == TRUE) {
  25.         /* grab token and advance past */
  26.         execstr = token(execstr, buffer, NPAT);
  27.  
  28.         /* evaluate it */
  29.         strcpy(buffer, fixnull(getval(buffer)));
  30.         if (strcmp(buffer, errorm) == 0)
  31.             return(FALSE);
  32.  
  33.         /* and look it up */
  34.         if ((kfunc = fncmatch(buffer)) == NULL) {
  35.             mlwrite(TEXT16);
  36. /*                          "[No such Function]" */
  37.             return(FALSE);
  38.         }
  39.         
  40.         /* and execute it  INTERACTIVE */
  41.         clexec = FALSE;
  42.         status = (*kfunc)(f, n);    /* call the function */
  43.         clexec = TRUE;
  44.         return(status);
  45.     }
  46.  
  47.     /* prompt the user to type a named command */
  48.     /* and get the function name to execute */
  49.     kfunc = getname(": ");
  50.     if (kfunc == NULL) {
  51.         mlwrite(TEXT16);
  52. /*                      "[No such function]" */
  53.         return(FALSE);
  54.     }
  55.  
  56.     /* and then execute the command */
  57.     return((*kfunc)(f, n));
  58. }
  59.  
  60. /*    execcmd:    Execute a command line command to be typed in
  61.             by the user                    */
  62.  
  63. PASCAL NEAR execcmd(f, n)
  64.  
  65. int f, n;    /* default Flag and Numeric argument */
  66.  
  67. {
  68.     register int status;        /* status return */
  69.     char cmdstr[NSTRING];        /* string holding command to execute */
  70.  
  71.     /* get the line wanted */
  72.     if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
  73.         return(status);
  74.  
  75.     execlevel = 0;
  76.     return(docmd(cmdstr));
  77. }
  78.  
  79. /*    docmd:    take a passed string as a command line and translate
  80.         it to be executed as a command. This function will be
  81.         used by execute-command-line and by all source and
  82.         startup files. Lastflag/thisflag is also updated.
  83.  
  84.     format of the command line is:
  85.  
  86.         {# arg} <command-name> {<argument string(s)>}
  87.  
  88. */
  89.  
  90. PASCAL NEAR docmd(cline)
  91.  
  92. char *cline;    /* command line to execute */
  93.  
  94. {
  95.     register int f;        /* default argument flag */
  96.     register int n;        /* numeric repeat value */
  97.     int (PASCAL NEAR *fnc)();/* function to execute */
  98.     BUFFER *bp;        /* buffer to execute */
  99.     int status;        /* return status of function */
  100.     int oldcle;        /* old contents of clexec flag */
  101.     char *oldestr;        /* original exec string */
  102.     char tkn[NSTRING];    /* next token off of command line */
  103.         char bufn[NBUFN+2];    /* name of buffer to execute */
  104.  
  105.     /* if we are scanning and not executing..go back here */
  106.     if (execlevel)
  107.         return(TRUE);
  108.  
  109.     oldestr = execstr;    /* save last ptr to string to execute */
  110.     execstr = cline;    /* and set this one as current */
  111.  
  112.     /* first set up the default command values */
  113.     f = FALSE;
  114.     n = 1;
  115.     lastflag = thisflag;
  116.     thisflag = 0;
  117.  
  118.     if ((status = macarg(tkn)) != TRUE) {    /* and grab the first token */
  119.         execstr = oldestr;
  120.         return(status);
  121.     }
  122.  
  123.     /* process leadin argument */
  124.     if (gettyp(tkn) != TKCMD) {
  125.         f = TRUE;
  126.         strcpy(tkn, fixnull(getval(tkn)));
  127.         n = asc_int(tkn);
  128.  
  129.         /* and now get the command to execute */
  130.         if ((status = macarg(tkn)) != TRUE) {
  131.             execstr = oldestr;
  132.             return(status);
  133.         }
  134.     }
  135.  
  136.     /* and match the token to see if it exists */
  137.     if ((fnc = fncmatch(tkn)) == NULL) {
  138.  
  139.         /* construct the buffer name */
  140.         strcpy(bufn, "[");
  141.         strcat(bufn, tkn);
  142.         strcat(bufn, "]");
  143.  
  144.         /* find the pointer to that buffer */
  145.             if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  146.             mlwrite(TEXT16);
  147. /*                          "[No such Function]" */
  148.             execstr = oldestr;
  149.             return(FALSE);
  150.         }
  151.  
  152.         /* execute the buffer */
  153.         oldcle = clexec;    /* save old clexec flag */
  154.         clexec = TRUE;        /* in cline execution */
  155.         while (n-- > 0)
  156.             if ((status = dobuf(bp)) != TRUE)
  157.                 break;
  158.         cmdstatus = status;    /* save the status */
  159.         clexec = oldcle;    /* restore clexec flag */
  160.         execstr = oldestr;
  161.         return(status);
  162.     }
  163.     
  164.     /* save the arguments and go execute the command */
  165.     oldcle = clexec;        /* save old clexec flag */
  166.     clexec = TRUE;            /* in cline execution */
  167.     status = (*fnc)(f, n);        /* call the function */
  168.     cmdstatus = status;        /* save the status */
  169.     clexec = oldcle;        /* restore clexec flag */
  170.     execstr = oldestr;
  171.     return(status);
  172. }
  173.  
  174. /* token:    chop a token off a string
  175.         return a pointer past the token
  176. */
  177.  
  178. char *PASCAL NEAR token(src, tok, size)
  179.  
  180. char *src, *tok;    /* source string, destination token string */
  181. int size;        /* maximum size of token */
  182.  
  183. {
  184.     register int quotef;    /* is the current string quoted? */
  185.     register char c;    /* temporary character */
  186.  
  187.     /* first scan past any whitespace in the source string */
  188.     while (*src == ' ' || *src == '\t')
  189.         ++src;
  190.  
  191.     /* scan through the source string */
  192.     quotef = FALSE;
  193.     while (*src) {
  194.         /* process special characters */
  195.         if (*src == '~') {
  196.             ++src;
  197.             if (*src == 0)
  198.                 break;
  199.             switch (*src++) {
  200.                 case 'r':    c = 13; break;
  201.                 case 'n':    c = 13; break;
  202.                 case 'l':    c = 10; break;
  203.                 case 't':    c = 9;  break;
  204.                 case 'b':    c = 8;  break;
  205.                 case 'f':    c = 12; break;
  206.                 default:    c = *(src-1);
  207.             }
  208.             if (--size > 0) {
  209.                 *tok++ = c;
  210.             }
  211.         } else {
  212.             /* check for the end of the token */
  213.             if (quotef) {
  214.                 if (*src == '"')
  215.                     break;
  216.             } else {
  217.                 if (*src == ' ' || *src == '\t')
  218.                     break;
  219.             }
  220.  
  221.             /* set quote mode if quote found */
  222.             if (*src == '"')
  223.                 quotef = TRUE;
  224.  
  225.             /* record the character */
  226.             c = *src++;
  227.             if (--size > 0)
  228.                 *tok++ = c;
  229.         }
  230.     }
  231.  
  232.     /* terminate the token and exit */
  233.     if (*src)
  234.         ++src;
  235.     *tok = 0;
  236.     return(src);
  237. }
  238.  
  239. PASCAL NEAR macarg(tok)    /* get a macro line argument */
  240.  
  241. char *tok;    /* buffer to place argument */
  242.  
  243. {
  244.     int savcle;    /* buffer to store original clexec */
  245.     int status;
  246.  
  247.     savcle = clexec;    /* save execution mode */
  248.     clexec = TRUE;        /* get the argument */
  249.     status = nextarg("", tok, NSTRING, ctoec('\r'));
  250.     clexec = savcle;    /* restore execution mode */
  251.     return(status);
  252. }
  253.  
  254. /*    nextarg:    get the next argument    */
  255.  
  256. PASCAL NEAR nextarg(prompt, buffer, size, terminator)
  257.  
  258. char *prompt;        /* prompt to use if we must be interactive */
  259. char *buffer;        /* buffer to put token into */
  260. int size;        /* size of the buffer */
  261. int terminator;        /* terminating char to be used on interactive fetch */
  262.  
  263. {
  264.     register char *sp;    /* return pointer from getval() */
  265.  
  266.     /* if we are interactive, go get it! */
  267.     if (clexec == FALSE) {
  268.         /* prompt the user for the input string */
  269.         if (discmd) {
  270.             if (prompt) mlwrite(prompt);
  271.         }
  272.         else
  273.             movecursor(term.t_nrow, 0);
  274.  
  275.         return(getstring(buffer, size, terminator));
  276.     }
  277.  
  278.     /* grab token and advance past */
  279.     execstr = token(execstr, buffer, size);
  280.  
  281.     /* evaluate it */
  282.     if ((sp = getval(buffer)) == NULL)
  283.         return(FALSE);
  284.     strcpy(buffer, sp);
  285.     return(TRUE);
  286. }
  287.  
  288. /*    storemac:    Set up a macro buffer and flag to store all
  289.             executed command lines there            */
  290.  
  291. PASCAL NEAR storemac(f, n)
  292.  
  293. int f;        /* default flag */
  294. int n;        /* macro number to use */
  295.  
  296. {
  297.     register struct BUFFER *bp;    /* pointer to macro buffer */
  298.     char bname[NBUFN];        /* name of buffer to use */
  299.  
  300.     /* must have a numeric argument to this function */
  301.     if (f == FALSE) {
  302.         mlwrite(TEXT111);
  303. /*                      "No macro specified" */
  304.         return(FALSE);
  305.     }
  306.  
  307.     /* range check the macro number */
  308.     if (n < 1 || n > 40) {
  309.         mlwrite(TEXT112);
  310. /*                      "Macro number out of range" */
  311.         return(FALSE);
  312.     }
  313.  
  314.     /* construct the macro buffer name */
  315.     strcpy(bname, "[Macro xx]");
  316.     bname[7] = '0' + (n / 10);
  317.     bname[8] = '0' + (n % 10);
  318.  
  319.     /* set up the new macro buffer */
  320.     if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  321.         mlwrite(TEXT113);
  322. /*                      "Can not create macro" */
  323.         return(FALSE);
  324.     }
  325.  
  326.     /* and make sure it is empty */
  327.     bclear(bp);
  328.  
  329.     /* and set the macro store pointers to it */
  330.     mstore = TRUE;
  331.     bstore = bp;
  332.     return(TRUE);
  333. }
  334.  
  335. /*    storeproc:    Set up a procedure buffer and flag to store all
  336.             executed command lines there            */
  337.  
  338. PASCAL NEAR storeproc(f, n)
  339.  
  340. int f;        /* default flag */
  341. int n;        /* macro number to use */
  342.  
  343. {
  344.     register struct BUFFER *bp;    /* pointer to macro buffer */
  345.     register int status;        /* return status */
  346.     char bname[NBUFN];        /* name of buffer to use */
  347.  
  348.     /* a numeric argument means its a numbered macro */
  349.     if (f == TRUE)
  350.         return(storemac(f, n));
  351.  
  352.     /* get the name of the procedure */
  353.         if ((status = mlreply(TEXT114, &bname[1], NBUFN-2)) != TRUE)
  354. /*                            "Procedure name: " */
  355.                 return(status);
  356.  
  357.     /* construct the macro buffer name */
  358.     bname[0] = '[';
  359.     strcat(bname, "]");
  360.  
  361.     /* set up the new macro buffer */
  362.     if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  363.         mlwrite(TEXT113);
  364. /*                      "Can not create macro" */
  365.         return(FALSE);
  366.     }
  367.  
  368.     /* and make sure it is empty */
  369.     bclear(bp);
  370.  
  371.     /* and set the macro store pointers to it */
  372.     mstore = TRUE;
  373.     bstore = bp;
  374.     return(TRUE);
  375. }
  376.  
  377. /*    execproc:    Execute a procedure                */
  378.  
  379. PASCAL NEAR execproc(f, n)
  380.  
  381. int f, n;    /* default flag and numeric arg */
  382.  
  383. {
  384.         register BUFFER *bp;        /* ptr to buffer to execute */
  385.         register int status;        /* status return */
  386.         char bufn[NBUFN+2];        /* name of buffer to execute */
  387.  
  388.     /* find out what buffer the user wants to execute */
  389.         if ((status = mlreply(TEXT115, &bufn[1], NBUFN)) != TRUE)
  390. /*                            "Execute procedure: " */
  391.                 return(status);
  392.  
  393.     /* construct the buffer name */
  394.     bufn[0] = '[';
  395.     strcat(bufn, "]");
  396.  
  397.     /* find the pointer to that buffer */
  398.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  399.         mlwrite(TEXT116);
  400. /*                      "No such procedure" */
  401.                 return(FALSE);
  402.         }
  403.  
  404.     /* and now execute it as asked */
  405.     while (n-- > 0)
  406.         if ((status = dobuf(bp)) != TRUE)
  407.             return(status);
  408.     return(TRUE);
  409. }
  410.  
  411. /*    execbuf:    Execute the contents of a buffer of commands    */
  412.  
  413. PASCAL NEAR execbuf(f, n)
  414.  
  415. int f, n;    /* default flag and numeric arg */
  416.  
  417. {
  418.         register BUFFER *bp;        /* ptr to buffer to execute */
  419.         register int status;        /* status return */
  420.  
  421.     /* find out what buffer the user wants to execute */
  422.     if ((bp = getcbuf(TEXT117, curbp->b_bname, FALSE)) == NULL)
  423. /*                        "Execute buffer: " */
  424.         return(ABORT);
  425.  
  426.     /* and now execute it as asked */
  427.     while (n-- > 0)
  428.         if ((status = dobuf(bp)) != TRUE)
  429.             return(status);
  430.     return(TRUE);
  431. }
  432.  
  433. /*    dobuf:    execute the contents of the buffer pointed to
  434.         by the passed BP
  435.  
  436.     Directives start with a "!" and include:
  437.  
  438.     !endm        End a macro
  439.     !if (cond)    conditional execution
  440.     !else
  441.     !endif
  442.     !return        Return (terminating current macro)
  443.     !goto <label>    Jump to a label in the current macro
  444.     !force        Force macro to continue...even if command fails
  445.     !while (cond)    Execute a loop if the condition is true
  446.     !endwhile
  447.     
  448.     Line Labels begin with a "*" as the first nonblank char, like:
  449.  
  450.     *LBL01
  451. */
  452.  
  453. PASCAL NEAR dobuf(bp)
  454.  
  455. BUFFER *bp;    /* buffer to execute */
  456.  
  457. {
  458.         register int status;    /* status return */
  459.     register LINE *lp;    /* pointer to line to execute */
  460.     register LINE *hlp;    /* pointer to line header */
  461.     register LINE *glp;    /* line to goto */
  462.     LINE *mp;        /* Macro line storage temp */
  463.     int dirnum;        /* directive index */
  464.     int linlen;        /* length of line to execute */
  465.     int i;            /* index */
  466.     int force;        /* force TRUE result? */
  467.     WINDOW *wp;        /* ptr to windows to scan */
  468.     WHBLOCK *whlist;    /* ptr to !WHILE list */
  469.     WHBLOCK *scanner;    /* ptr during scan */
  470.     WHBLOCK *whtemp;    /* temporary ptr to a WHBLOCK */
  471.     char *einit;        /* initial value of eline */
  472.     char *eline;        /* text of line to execute */
  473.     char tkn[NSTRING];    /* buffer to evaluate an expresion in */
  474. #if    LOGFLG
  475.     FILE *fp;        /* file handle for log file */
  476. #endif
  477. #if    DEBUGM
  478.     int skipflag;        /* are we skipping debugging a function? */
  479. #endif
  480.  
  481.     /* clear IF level flags/while ptr */
  482.     execlevel = 0;
  483.     whlist = NULL;
  484.     scanner = NULL;
  485.  
  486.     /* flag we are executing the buffer */
  487.     bp->b_exec += 1;
  488.  
  489. #if    DEBUGM
  490.     /* we are not skipping a function yet (for the debugger) */
  491.     skipflag = FALSE;
  492. #endif
  493.  
  494.     /* scan the buffer to execute, building WHILE header blocks */
  495.     hlp = bp->b_linep;
  496.     lp = lforw(hlp);
  497.     while (lp != hlp) {
  498.  
  499.         /* scan the current line */
  500.         eline = ltext(lp);
  501.         i = lused(lp);
  502.  
  503.         /* trim leading whitespace */
  504.         while (i-- > 0 && (*eline == ' ' || *eline == '\t'))
  505.             ++eline;
  506.  
  507.         /* if theres nothing here, don't bother */
  508.         if (i <= 0)
  509.             goto nxtscan;
  510.  
  511.         /* if is a while directive, make a block... */
  512.         if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') {
  513.             whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  514.             if (whtemp == NULL) {
  515. noram:                errormesg(TEXT119, bp, lp);
  516. /*                                        "%%Out of memory during while scan" */
  517. failexit:            freewhile(scanner);
  518.                 goto eabort;
  519.             }
  520.             whtemp->w_begin = lp;
  521.             whtemp->w_type = BTWHILE;
  522.             whtemp->w_next = scanner;
  523.             scanner = whtemp;
  524.         }
  525.  
  526.         /* if is a BREAK directive, make a block... */
  527.         if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') {
  528.             if (scanner == NULL) {
  529.                 errormesg(TEXT120, bp, lp);
  530. /*                                        "%%!BREAK outside of any !WHILE loop" */
  531.                 goto failexit;
  532.             }
  533.             whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  534.             if (whtemp == NULL)
  535.                 goto noram;
  536.             whtemp->w_begin = lp;
  537.             whtemp->w_type = BTBREAK;
  538.             whtemp->w_next = scanner;
  539.             scanner = whtemp;
  540.         }
  541.  
  542.         /* if it is an endwhile directive, record the spot... */
  543.         if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) {
  544.             if (scanner == NULL) {
  545.                 errormesg(TEXT121, bp, lp);
  546. /*                                      "%%!ENDWHILE with no preceding !WHILE" */
  547.                 goto failexit;
  548.             }
  549.             /* move top records from the scanner list to the
  550.                whlist until we have moved all BREAK records
  551.                and one WHILE record */
  552.             do {
  553.                 scanner->w_end = lp;
  554.                 whtemp = whlist;
  555.                 whlist = scanner;
  556.                 scanner = scanner->w_next;
  557.                 whlist->w_next = whtemp;
  558.             } while (whlist->w_type == BTBREAK);
  559.         }
  560.  
  561. nxtscan:    /* on to the next line */
  562.         lp = lforw(lp);
  563.     }
  564.  
  565.     /* while and endwhile should match! */
  566.     if (scanner != NULL) {
  567.         errormesg(TEXT122, bp, lp);
  568. /*                      "%%!WHILE with no matching !ENDWHILE" */
  569.         goto failexit;
  570.     }
  571.  
  572.     /* let the first command inherit the flags from the last one..*/
  573.     thisflag = lastflag;
  574.  
  575.     /* starting at the beginning of the buffer */
  576.     hlp = bp->b_linep;
  577.     lp = lforw(hlp);
  578.     while (lp != hlp && eexitflag == FALSE) {
  579.  
  580.         /* allocate eline and copy macro line to it */
  581.         linlen = lused(lp);
  582.         if ((einit = eline = malloc(linlen+1)) == NULL) {
  583.             errormesg(TEXT123, bp, lp);
  584. /*                              "%%Out of Memory during macro execution" */
  585.             freewhile(whlist);
  586.             bp->b_exec -= 1;
  587.             return(FALSE);
  588.         }
  589.         bytecopy(eline, ltext(lp), linlen);
  590.         eline[linlen] = 0;    /* make sure it ends */
  591.  
  592.         /* trim leading whitespace */
  593.         while (*eline == ' ' || *eline == '\t')
  594.             ++eline;
  595.  
  596.         /* dump comments and blank lines */
  597.         if (*eline == ';' || *eline == 0)
  598.             goto onward;
  599.  
  600. #if    LOGFLG
  601.         /* append the current command to the log file */
  602.         fp = fopen("emacs.log", "a");
  603.         strcpy(outline, eline);
  604.         fprintf(fp, "%s", outline);
  605.         fclose(fp);
  606. #endif
  607.     
  608. #if    DEBUGM
  609.         /* only do this if we are debugging */
  610.         if (macbug && !mstore && (execlevel == 0))
  611.             if (debug(bp, eline, &skipflag) == FALSE) {
  612.                 errormesg(TEXT54, bp, lp);
  613. /*                                      "[Macro aborted]" */
  614.                 goto eabort;
  615.             }
  616. #endif
  617.  
  618.         /* Parse directives here.... */
  619.         dirnum = -1;
  620.         if (*eline == '!') {
  621.             /* Find out which directive this is */
  622.             ++eline;
  623.             for (dirnum = 0; dirnum < NUMDIRS; dirnum++)
  624.                 if (strncmp(eline, dname[dirnum],
  625.                             dname_len[dirnum]) == 0)
  626.                     break;
  627.  
  628.             /* and bitch if it's illegal */
  629.             if (dirnum == NUMDIRS) {
  630.                 errormesg(TEXT124, bp, lp);
  631. /*                                      "%%Unknown Directive" */
  632.                 goto eabort;
  633.             }
  634.  
  635.             /* service only the !ENDM macro here */
  636.             if (dirnum == DENDM) {
  637.                 mstore = FALSE;
  638.                 bstore = NULL;
  639.                 goto onward;
  640.             }
  641.  
  642.             /* restore the original eline....*/
  643.             --eline;
  644.         }
  645.  
  646.         /* if macro store is on, just salt this away */
  647.         if (mstore) {
  648.             /* allocate the space for the line */
  649.             linlen = strlen(eline);
  650.             if ((mp=lalloc(linlen)) == NULL) {
  651.                 errormesg(TEXT125, bp, lp);
  652. /*                                      "Out of memory while storing macro" */
  653.                 goto eabort;
  654.             }
  655.     
  656.             /* copy the text into the new line */
  657.             for (i=0; i<linlen; ++i)
  658.                 lputc(mp, i, eline[i]);
  659.     
  660.             /* attach the line to the end of the buffer */
  661.                    bstore->b_linep->l_bp->l_fp = mp;
  662.             mp->l_bp = bstore->b_linep->l_bp;
  663.             bstore->b_linep->l_bp = mp;
  664.             mp->l_fp = bstore->b_linep;
  665.             goto onward;
  666.         }
  667.     
  668.         force = FALSE;
  669.  
  670.         /* dump comments */
  671.         if (*eline == '*')
  672.             goto onward;
  673.  
  674.         /* now, execute directives */
  675.         if (dirnum != -1) {
  676.             /* skip past the directive */
  677.             while (*eline && *eline != ' ' && *eline != '\t')
  678.                 ++eline;
  679.             execstr = eline;
  680.  
  681.             switch (dirnum) {
  682.             case DIF:    /* IF directive */
  683.                 /* grab the value of the logical exp */
  684.                 if (execlevel == 0) {
  685.                     if (macarg(tkn) != TRUE) {
  686.                         free(einit);
  687.                         goto eexec;
  688.                     }
  689.                     if (stol(tkn) == FALSE)
  690.                         ++execlevel;
  691.                 } else
  692.                     ++execlevel;
  693.                 goto onward;
  694.  
  695.             case DWHILE:    /* WHILE directive */
  696.                 /* grab the value of the logical exp */
  697.                 if (execlevel == 0) {
  698.                     if (macarg(tkn) != TRUE) {
  699.                         free(einit);
  700.                         goto eexec;
  701.                     }
  702.                     if (stol(tkn) == TRUE)
  703.                         goto onward;
  704.                 }
  705.                 /* drop down and act just like !BREAK */
  706.  
  707.             case DBREAK:    /* BREAK directive */
  708.                 if (dirnum == DBREAK && execlevel)
  709.                     goto onward;
  710.  
  711.                 /* jump down to the endwhile */
  712.                 /* find the right while loop */
  713.                 whtemp = whlist;
  714.                 while (whtemp) {
  715.                     if (whtemp->w_begin == lp)
  716.                         break;
  717.                     whtemp = whtemp->w_next;
  718.                 }
  719.             
  720.                 if (whtemp == NULL) {
  721.                     errormesg(TEXT126, bp, lp);
  722. /*                                              "%%Internal While loop error" */
  723.                     goto eabort;
  724.                 }
  725.             
  726.                 /* reset the line pointer back.. */
  727.                 lp = whtemp->w_end;
  728.                 goto onward;
  729.  
  730.             case DELSE:    /* ELSE directive */
  731.                 if (execlevel == 1)
  732.                     --execlevel;
  733.                 else if (execlevel == 0 )
  734.                     ++execlevel;
  735.                 goto onward;
  736.  
  737.             case DENDIF:    /* ENDIF directive */
  738.                 if (execlevel)
  739.                     --execlevel;
  740.                 goto onward;
  741.  
  742.             case DGOTO:    /* GOTO directive */
  743.                 /* .....only if we are currently executing */
  744.                 if (execlevel == 0) {
  745.  
  746. #if WINDOW_MSWIN
  747.                     longop(TRUE);
  748. #endif
  749.                     /* grab label to jump to */
  750.                     eline = token(eline, golabel, NPAT);
  751.                     linlen = strlen(golabel);
  752.                     glp = lforw(hlp);
  753.                     while (glp != hlp) {
  754.                         if ((lused(glp) >= linlen) &&
  755.                             (lgetc(glp, 0) == '*') &&
  756.                             (strncmp(((char *)ltext(glp)) + 1,
  757.                                     golabel, linlen) == 0)) {
  758.                             lp = glp;
  759.                             goto onward;
  760.                         }
  761.                         glp = lforw(glp);
  762.                     }
  763.                     errormesg(TEXT127, bp, lp);
  764. /*                                              "%%No such label" */
  765.                     goto eabort;
  766.                 }
  767.                 goto onward;
  768.     
  769.             case DRETURN:    /* RETURN directive */
  770.                 if (execlevel == 0) {
  771.                     free(einit);
  772.                     goto eexec;
  773.                 }
  774.                 goto onward;
  775.  
  776.             case DENDWHILE:    /* ENDWHILE directive */
  777.                 if (execlevel) {
  778.                     --execlevel;
  779.                     goto onward;
  780.                 } else {
  781. #if WINDOW_MSWIN
  782.                     longop(TRUE);
  783. #endif
  784.                     /* find the right while loop */
  785.                     whtemp = whlist;
  786.                     while (whtemp) {
  787.                         if (whtemp->w_type == BTWHILE &&
  788.                              whtemp->w_end == lp)
  789.                             break;
  790.                         whtemp = whtemp->w_next;
  791.                     }
  792.         
  793.                     if (whtemp == NULL) {
  794.                         errormesg(TEXT126, bp, lp);
  795. /*                                                      "%%Internal While loop error" */
  796.                         goto eabort;
  797.                     }
  798.         
  799.                     /* reset the line pointer back.. */
  800.                     lp = lback(whtemp->w_begin);
  801.                     goto onward;
  802.                 }
  803.  
  804.             case DFORCE:    /* FORCE directive */
  805.                 force = TRUE;
  806.  
  807.             }
  808.         }
  809.  
  810.         /* execute the statement */
  811.         status = docmd(eline);
  812.         if (force)        /* force the status */
  813.             status = TRUE;
  814.  
  815. #if    LOGFLG
  816.         /* append the current command to the log file */
  817.         fp = fopen("emacs.log", "a");
  818.         fprintf(fp, ". . . done\n");
  819.         fclose(fp);
  820. #endif
  821.  
  822.         /* check for a command error */
  823.         if (status != TRUE) {
  824.  
  825.             /* look if buffer is showing */
  826.             wp = wheadp;
  827.             while (wp != NULL) {
  828.                 if (wp->w_bufp == bp) {
  829.                     /* and point it */
  830.                     wp->w_dotp = lp;
  831.                     wp->w_doto = 0;
  832.                     wp->w_flag |= WFHARD;
  833.                 }
  834.                 wp = wp->w_wndp;
  835.             }
  836.  
  837.             /* in any case set the buffer . */
  838.             bp->b_dotp = lp;
  839.             bp->b_doto = 0;
  840.  
  841.             errormesg(TEXT219, bp, lp);
  842. /*                  "%%Macro Failed" */
  843.  
  844.             execlevel = 0;
  845.             freewhile(whlist);
  846.             bp->b_exec -= 1;
  847.             free(einit);
  848.             return(status);
  849.         }
  850.  
  851. onward:        /* on to the next line */
  852.         free(einit);
  853.         lp = lforw(lp);
  854. #if    DEBUGM
  855.         if (skipflag)
  856.             macbug = TRUE;
  857. #endif
  858.     }
  859.  
  860. eexec:    /* exit the current function */
  861.     execlevel = 0;
  862.     freewhile(whlist);
  863.     bp->b_exec -= 1;
  864.         return(TRUE);
  865.  
  866. eabort:    /* exit the current function with a failure */
  867.     execlevel = 0;
  868.     freewhile(whlist);
  869.     bp->b_exec -= 1;
  870.     free(einit);
  871.         return(FALSE);
  872. }
  873.  
  874. /* errormesg:    display a macro execution error along with the buffer and
  875.         line currently being executed */
  876.  
  877. VOID PASCAL NEAR errormesg(mesg, bp, lp)
  878.  
  879. char *mesg;    /* error message to display */
  880. BUFFER *bp;    /* buffer error occured in */
  881. LINE *lp;    /* line " */
  882.  
  883. {
  884.     char buf[NSTRING];
  885.  
  886.     exec_error = TRUE;
  887.  
  888.     /* build error message line */
  889.     strcpy(buf, "\n");
  890.     strcat(buf, mesg);
  891.     strcat(buf, TEXT229);
  892. /*        " in < " */
  893.     strcat(buf, bp->b_bname);
  894.     strcat(buf, TEXT230);
  895. /*        "> at line " */
  896.     strcat(buf, long_asc(getlinenum(bp, lp)));
  897.     mlforce(buf);
  898. }
  899.  
  900. #if    DEBUGM
  901. /*        Interactive debugger
  902.  
  903.         if $debug == TRUE, The interactive debugger is invoked
  904.         commands are listed out with the ? key            */
  905.  
  906. PASCAL NEAR debug(bp, eline, skipflag)
  907.  
  908. BUFFER *bp;    /* buffer to execute */
  909. char *eline;    /* text of line to debug */
  910. int *skipflag;    /* are we skipping debugging? */
  911.  
  912. {
  913.     register int oldcmd;        /* original command display flag */
  914.     register int oldinp;        /* original connamd input flag */
  915.     register int oldstatus;        /* status of last command */
  916.     register int c;            /* temp character */
  917.     register KEYTAB *key;        /* ptr to a key entry */
  918.     static char track[NSTRING] = "";/* expression to track value of */
  919.     char temp[NSTRING];        /* command or expression */
  920.  
  921. dbuild:    /* Build the information line to be presented to the user */
  922.  
  923.     strcpy(outline, "<<<");
  924.  
  925.     /* display the tracked expression */
  926.     if (track[0] != 0) {
  927.         oldstatus = cmdstatus;
  928.         docmd(track);
  929.         cmdstatus = oldstatus;
  930.         strcat(outline, "[=");
  931.         strcat(outline, gtusr("track"));
  932.         strcat(outline, "]");
  933.     }
  934.  
  935.     /* debug macro name */
  936.     strcat(outline, bp->b_bname);
  937.     strcat(outline, ":");
  938.  
  939.     /* and lastly the line */
  940.     strcat(outline, eline);
  941.     strcat(outline, ">>>");
  942.  
  943.     /* expand the %'s so mlwrite() won't interpret them */
  944.     makelit(outline);
  945.  
  946.     /* write out the debug line */
  947. dinput:    outline[term.t_ncol - 1] = 0;
  948.     mlforce(outline);
  949.     update(TRUE);
  950.  
  951.     /* and get the keystroke */
  952.     c = getkey();
  953.  
  954.     /* ignore the mouse here */
  955.     if (c & MOUS)
  956.         goto dinput;
  957.  
  958.     /* META key turns off debugging */
  959.     key = getbind(c);
  960.     if (key && key->k_type == BINDFNC && key && key->k_ptr.fp == meta)
  961.         macbug = FALSE;
  962.  
  963.     else if (c == abortc) {
  964.         return(FALSE);
  965.  
  966.     } else switch (c) {
  967.  
  968.         case '?': /* list commands */
  969.             strcpy(outline, TEXT128);
  970. /*"(e)val exp, (c/x)ommand, (t)rack exp, (^G)abort, <SP>exec, <META> stop debug"*/
  971.             goto dinput;
  972.  
  973.         case 'c': /* execute statement */
  974.             oldcmd = discmd;
  975.             discmd = TRUE;
  976.             oldinp = disinp;
  977.             disinp = TRUE;
  978.             execcmd(FALSE, 1);
  979.             discmd = oldcmd;
  980.             disinp = oldinp;
  981.             goto dbuild;
  982.  
  983.         case 'x': /* execute extended command */
  984.             oldcmd = discmd;
  985.             discmd = TRUE;
  986.             oldinp = disinp;
  987.             disinp = TRUE;
  988.             oldstatus = cmdstatus;
  989.             namedcmd(FALSE, 1);
  990.             cmdstatus = oldstatus;
  991.             discmd = oldcmd;
  992.             disinp = oldinp;
  993.             goto dbuild;
  994.  
  995.         case 'e': /* evaluate expresion */
  996.             strcpy(temp, "set %track ");
  997.             oldinp = disinp;
  998.             disinp = TRUE;
  999.             mlwrite("Exp:");
  1000.             getstring(&temp[11], NSTRING, ctoec(RETCHAR));
  1001.             disinp = oldinp;
  1002.             oldstatus = cmdstatus;
  1003.             docmd(temp);
  1004.             cmdstatus = oldstatus;
  1005.             strcpy(temp, " = [");
  1006.             strcat(temp, gtusr("track"));
  1007.             strcat(temp, "]");
  1008.             mlforce(temp);
  1009.             c = getkey();
  1010.             goto dinput;
  1011.  
  1012.         case 't': /* track expresion */
  1013.             oldinp = disinp;
  1014.             disinp = TRUE;
  1015.             mlwrite("Exp: ");
  1016.             getstring(temp, NSTRING, ctoec(RETCHAR));
  1017.             disinp = oldinp;
  1018.             strcpy(track, "set %track ");
  1019.             strcat(track, temp);
  1020.             goto dbuild;
  1021.  
  1022.         case 's': /* execute a function */
  1023.             *skipflag = TRUE;
  1024.             macbug = FALSE;
  1025.             break;
  1026.  
  1027.         case ' ': /* execute a statement */
  1028.             break;
  1029.  
  1030.         default: /* illegal command */
  1031.             TTbeep();
  1032.             goto dbuild;
  1033.     }
  1034.     return(TRUE);
  1035. }
  1036. #endif
  1037.  
  1038. VOID PASCAL NEAR makelit(s)        /* expand all "%" to "%%" */
  1039.  
  1040. char *s;    /* string to expand */
  1041.  
  1042. {
  1043.     register char *sp;    /* temp for expanding string */
  1044.     register char *ep;    /* ptr to end of string to expand */
  1045.  
  1046.     sp = s;
  1047.     while (*sp)
  1048.     if (*sp++ == '%') {
  1049.         /* advance to the end */
  1050.         ep = --sp;
  1051.         while (*ep++)
  1052.             ;
  1053.         /* null terminate the string one out */
  1054.         *(ep + 1) = 0;
  1055.         /* copy backwards */
  1056.         while(ep-- > sp)
  1057.             *(ep + 1) = *ep;
  1058.  
  1059.         /* and advance sp past the new % */
  1060.         sp += 2;                    
  1061.     }
  1062. }
  1063.  
  1064. VOID PASCAL NEAR freewhile(wp)    /* free a list of while block pointers */
  1065.  
  1066. WHBLOCK *wp;    /* head of structure to free */
  1067.  
  1068. {
  1069.     if (wp != NULL)
  1070.     {
  1071.         freewhile(wp->w_next);
  1072.         free((char *) wp);
  1073.     }
  1074. }
  1075.  
  1076. PASCAL NEAR execfile(f, n)    /* execute a series of commands in a file */
  1077.  
  1078. int f, n;    /* default flag and numeric arg to pass on to file */
  1079.  
  1080. {
  1081.     register int status;    /* return status of name query */
  1082.     char fname[NSTRING];    /* name of file to execute */
  1083.     char *fspec;        /* full file spec */
  1084.  
  1085. #if WINDOW_MSWIN
  1086.     /* special case: we want filenamedlg to refrain from stuffing a
  1087.        full pathname so that flook() can be put to use a few lines
  1088.        down the road... */
  1089.     if ((status = filenamedlg(TEXT129, fname, NSTRING -1, FALSE)) != TRUE)
  1090. #else
  1091.     if ((status = mlreply(TEXT129, fname, NSTRING -1)) != TRUE)
  1092. #endif
  1093.         return(status);
  1094.  
  1095.     /* look up the path for the file */
  1096.     fspec = flook(fname, TRUE);
  1097.  
  1098.     /* if it isn't around */
  1099.     if (fspec == NULL) {
  1100.  
  1101.         /* try to default the extension */
  1102.         if (sindex(fname, ".") == 0) {
  1103.             strcat(fname, ".cmd");
  1104.             fspec = flook(fname, TRUE);
  1105.             if (fspec != NULL)
  1106.                 goto exec1;
  1107.         }
  1108.  
  1109.         /* complain if we are interactive */
  1110.         if (clexec == FALSE)
  1111.             mlwrite(TEXT214, fname);
  1112. /*                    "%%No such file as %s" */
  1113.         return(FALSE);
  1114.     }
  1115.  
  1116. exec1:    /* otherwise, execute it */
  1117.     while (n-- > 0)
  1118.         if ((status=dofile(fspec)) != TRUE)
  1119.             return(status);
  1120.  
  1121.     return(TRUE);
  1122. }
  1123.  
  1124. /*    dofile:    yank a file into a buffer and execute it
  1125.         if there are no errors, delete the buffer on exit */
  1126.  
  1127. PASCAL NEAR dofile(fname)
  1128.  
  1129. char *fname;    /* file name to execute */
  1130.  
  1131. {
  1132.     register BUFFER *bp;    /* buffer to place file to exeute */
  1133.     register BUFFER *cb;    /* temp to hold current buf while we read */
  1134.     register int status;    /* results of various calls */
  1135.     char bname[NBUFN];    /* name of buffer */
  1136.  
  1137.     makename(bname, fname);        /* derive the name of the buffer */
  1138.     unqname(bname);            /* make sure we don't stomp things */
  1139.     if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
  1140.         return(FALSE);
  1141.  
  1142.     bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  1143.     cb = curbp;        /* save the old buffer */
  1144.     curbp = bp;        /* make this one current */
  1145.     /* and try to read in the file to execute */
  1146.     if ((status = readin(fname, FALSE)) != TRUE) {
  1147.         curbp = cb;    /* restore the current buffer */
  1148.         return(status);
  1149.     }
  1150.  
  1151.     /* go execute it! */
  1152.     curbp = cb;        /* restore the current buffer */
  1153.     if ((status = dobuf(bp)) != TRUE)
  1154.         return(status);
  1155.  
  1156.     /* if not displayed, remove the now unneeded buffer and exit */
  1157.     if (bp->b_nwnd == 0)
  1158.         zotbuf(bp);
  1159.     return(TRUE);
  1160. }
  1161.  
  1162. /*    cbuf:    Execute the contents of a numbered buffer    */
  1163.  
  1164. PASCAL NEAR cbuf(f, n, bufnum)
  1165.  
  1166. int f, n;    /* default flag and numeric arg */
  1167. int bufnum;    /* number of buffer to execute */
  1168.  
  1169. {
  1170.         register BUFFER *bp;        /* ptr to buffer to execute */
  1171.         register int status;        /* status return */
  1172.     static char bufname[] = "[Macro xx]";
  1173.  
  1174.     /* make the buffer name */
  1175.     bufname[7] = '0' + (bufnum / 10);
  1176.     bufname[8] = '0' + (bufnum % 10);
  1177.  
  1178.     /* find the pointer to that buffer */
  1179.         if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
  1180.             mlwrite(TEXT130);
  1181. /*                      "Macro not defined" */
  1182.                 return(FALSE);
  1183.         }
  1184.  
  1185.     /* and now execute it as asked */
  1186.     while (n-- > 0)
  1187.         if ((status = dobuf(bp)) != TRUE)
  1188.             return(status);
  1189.     return(TRUE);
  1190. }
  1191.  
  1192. PASCAL NEAR cbuf1(f, n)
  1193.  
  1194. int f, n;    /* flag and numeric argument */
  1195.  
  1196. {
  1197.     return(cbuf(f, n, 1));
  1198. }
  1199.  
  1200. PASCAL NEAR cbuf2(f, n)
  1201.  
  1202. int f, n;    /* flag and numeric argument */
  1203.  
  1204. {
  1205.     return(cbuf(f, n, 2));
  1206. }
  1207.  
  1208. PASCAL NEAR cbuf3(f, n)
  1209.  
  1210. int f, n;    /* flag and numeric argument */
  1211.  
  1212. {
  1213.     return(cbuf(f, n, 3));
  1214. }
  1215.  
  1216. PASCAL NEAR cbuf4(f, n)
  1217.  
  1218. int f, n;    /* flag and numeric argument */
  1219.  
  1220. {
  1221.     return(cbuf(f, n, 4));
  1222. }
  1223.  
  1224. PASCAL NEAR cbuf5(f, n)
  1225.  
  1226. int f, n;    /* flag and numeric argument */
  1227.  
  1228. {
  1229.     return(cbuf(f, n, 5));
  1230. }
  1231.  
  1232. PASCAL NEAR cbuf6(f, n)
  1233.  
  1234. int f, n;    /* flag and numeric argument */
  1235.  
  1236. {
  1237.     return(cbuf(f, n, 6));
  1238. }
  1239.  
  1240. PASCAL NEAR cbuf7(f, n)
  1241.  
  1242. int f, n;    /* flag and numeric argument */
  1243.  
  1244. {
  1245.     return(cbuf(f, n, 7));
  1246. }
  1247.  
  1248. PASCAL NEAR cbuf8(f, n)
  1249.  
  1250. int f, n;    /* flag and numeric argument */
  1251.  
  1252. {
  1253.     return(cbuf(f, n, 8));
  1254. }
  1255.  
  1256. PASCAL NEAR cbuf9(f, n)
  1257.  
  1258. int f, n;    /* flag and numeric argument */
  1259.  
  1260. {
  1261.     return(cbuf(f, n, 9));
  1262. }
  1263.  
  1264. PASCAL NEAR cbuf10(f, n)
  1265.  
  1266. int f, n;    /* flag and numeric argument */
  1267.  
  1268. {
  1269.     return(cbuf(f, n, 10));
  1270. }
  1271.  
  1272. PASCAL NEAR cbuf11(f, n)
  1273.  
  1274. int f, n;    /* flag and numeric argument */
  1275.  
  1276. {
  1277.     return(cbuf(f, n, 11));
  1278. }
  1279.  
  1280. PASCAL NEAR cbuf12(f, n)
  1281.  
  1282. int f, n;    /* flag and numeric argument */
  1283.  
  1284. {
  1285.     return(cbuf(f, n, 12));
  1286. }
  1287.  
  1288. PASCAL NEAR cbuf13(f, n)
  1289.  
  1290. int f, n;    /* flag and numeric argument */
  1291.  
  1292. {
  1293.     return(cbuf(f, n, 13));
  1294. }
  1295.  
  1296. PASCAL NEAR cbuf14(f, n)
  1297.  
  1298. int f, n;    /* flag and numeric argument */
  1299.  
  1300. {
  1301.     return(cbuf(f, n, 14));
  1302. }
  1303.  
  1304. PASCAL NEAR cbuf15(f, n)
  1305.  
  1306. int f, n;    /* flag and numeric argument */
  1307.  
  1308. {
  1309.     return(cbuf(f, n, 15));
  1310. }
  1311.  
  1312. PASCAL NEAR cbuf16(f, n)
  1313.  
  1314. int f, n;    /* flag and numeric argument */
  1315.  
  1316. {
  1317.     return(cbuf(f, n, 16));
  1318. }
  1319.  
  1320. PASCAL NEAR cbuf17(f, n)
  1321.  
  1322. int f, n;    /* flag and numeric argument */
  1323.  
  1324. {
  1325.     return(cbuf(f, n, 17));
  1326. }
  1327.  
  1328. PASCAL NEAR cbuf18(f, n)
  1329.  
  1330. int f, n;    /* flag and numeric argument */
  1331.  
  1332. {
  1333.     return(cbuf(f, n, 18));
  1334. }
  1335.  
  1336. PASCAL NEAR cbuf19(f, n)
  1337.  
  1338. int f, n;    /* flag and numeric argument */
  1339.  
  1340. {
  1341.     return(cbuf(f, n, 19));
  1342. }
  1343.  
  1344. PASCAL NEAR cbuf20(f, n)
  1345.  
  1346. int f, n;    /* flag and numeric argument */
  1347.  
  1348. {
  1349.     return(cbuf(f, n, 20));
  1350. }
  1351.  
  1352. PASCAL NEAR cbuf21(f, n)
  1353.  
  1354. int f, n;    /* flag and numeric argument */
  1355.  
  1356. {
  1357.     return(cbuf(f, n, 21));
  1358. }
  1359.  
  1360. PASCAL NEAR cbuf22(f, n)
  1361.  
  1362. int f, n;    /* flag and numeric argument */
  1363.  
  1364. {
  1365.     return(cbuf(f, n, 22));
  1366. }
  1367.  
  1368. PASCAL NEAR cbuf23(f, n)
  1369.  
  1370. int f, n;    /* flag and numeric argument */
  1371.  
  1372. {
  1373.     return(cbuf(f, n, 23));
  1374. }
  1375.  
  1376. PASCAL NEAR cbuf24(f, n)
  1377.  
  1378. int f, n;    /* flag and numeric argument */
  1379.  
  1380. {
  1381.     return(cbuf(f, n, 24));
  1382. }
  1383.  
  1384. PASCAL NEAR cbuf25(f, n)
  1385.  
  1386. int f, n;    /* flag and numeric argument */
  1387.  
  1388. {
  1389.     return(cbuf(f, n, 25));
  1390. }
  1391.  
  1392. PASCAL NEAR cbuf26(f, n)
  1393.  
  1394. int f, n;    /* flag and numeric argument */
  1395.  
  1396. {
  1397.     return(cbuf(f, n, 26));
  1398. }
  1399.  
  1400. PASCAL NEAR cbuf27(f, n)
  1401.  
  1402. int f, n;    /* flag and numeric argument */
  1403.  
  1404. {
  1405.     return(cbuf(f, n, 27));
  1406. }
  1407.  
  1408. PASCAL NEAR cbuf28(f, n)
  1409.  
  1410. int f, n;    /* flag and numeric argument */
  1411.  
  1412. {
  1413.     return(cbuf(f, n, 28));
  1414. }
  1415.  
  1416. PASCAL NEAR cbuf29(f, n)
  1417.  
  1418. int f, n;    /* flag and numeric argument */
  1419.  
  1420. {
  1421.     return(cbuf(f, n, 29));
  1422. }
  1423.  
  1424. PASCAL NEAR cbuf30(f, n)
  1425.  
  1426. int f, n;    /* flag and numeric argument */
  1427.  
  1428. {
  1429.     return(cbuf(f, n, 30));
  1430. }
  1431.  
  1432. PASCAL NEAR cbuf31(f, n)
  1433.  
  1434. int f, n;    /* flag and numeric argument */
  1435.  
  1436. {
  1437.     return(cbuf(f, n, 31));
  1438. }
  1439.  
  1440. PASCAL NEAR cbuf32(f, n)
  1441.  
  1442. int f, n;    /* flag and numeric argument */
  1443.  
  1444. {
  1445.     return(cbuf(f, n, 32));
  1446. }
  1447.  
  1448. PASCAL NEAR cbuf33(f, n)
  1449.  
  1450. int f, n;    /* flag and numeric argument */
  1451.  
  1452. {
  1453.     return(cbuf(f, n, 33));
  1454. }
  1455.  
  1456. PASCAL NEAR cbuf34(f, n)
  1457.  
  1458. int f, n;    /* flag and numeric argument */
  1459.  
  1460. {
  1461.     return(cbuf(f, n, 34));
  1462. }
  1463.  
  1464. PASCAL NEAR cbuf35(f, n)
  1465.  
  1466. int f, n;    /* flag and numeric argument */
  1467.  
  1468. {
  1469.     return(cbuf(f, n, 35));
  1470. }
  1471.  
  1472. PASCAL NEAR cbuf36(f, n)
  1473.  
  1474. int f, n;    /* flag and numeric argument */
  1475.  
  1476. {
  1477.     return(cbuf(f, n, 36));
  1478. }
  1479.  
  1480. PASCAL NEAR cbuf37(f, n)
  1481.  
  1482. int f, n;    /* flag and numeric argument */
  1483.  
  1484. {
  1485.     return(cbuf(f, n, 37));
  1486. }
  1487.  
  1488. PASCAL NEAR cbuf38(f, n)
  1489.  
  1490. int f, n;    /* flag and numeric argument */
  1491.  
  1492. {
  1493.     return(cbuf(f, n, 38));
  1494. }
  1495.  
  1496. PASCAL NEAR cbuf39(f, n)
  1497.  
  1498. int f, n;    /* flag and numeric argument */
  1499.  
  1500. {
  1501.     return(cbuf(f, n, 39));
  1502. }
  1503.  
  1504. PASCAL NEAR cbuf40(f, n)
  1505.  
  1506. int f, n;    /* flag and numeric argument */
  1507.  
  1508. {
  1509.     return(cbuf(f, n, 40));
  1510. }
  1511.  
  1512.  
  1513.